////////////////////////////////////////////////////////////////////////////////////////
//
// JSimpleSim - A machine language simulator based on SimpSim by Anne-Gert Bultena.
//
// Copyright (C) 2008 Gerardo Camorlinga, Ryan Fitzgerald, and RJ Gordon
//
// This file is part of JSimpleSim.
//
// JSimpleSim is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// JSimpleSim is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with JSimpleSim.  If not, see <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////////////

package jsimplesim.view;

import java.awt.*;
import jsimplesim.view.components.StackTable;
import jsimplesim.view.components.HexCellEditor;
import jsimplesim.view.components.RegisterTable;
import jsimplesim.view.components.HexTable;
import jsimplesim.view.renderers.HexCellRenderer;
import jsimplesim.view.renderers.TabListCellRenderer;
import jsimplesim.*;
import org.jdesktop.application.Action;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.filechooser.*;
import java.io.*;
import java.util.*;
import jsimplesim.machine.Machine;
import org.apache.log4j.Logger;
import jsimplesim.model.*;
import java.awt.Font;
import org.jdesktop.application.Task;
import javax.help.*;
import java.net.URL;


/**
 * The application's main frame. Where all the magic happens
 * 
 * @author f08maroon
 */
public class JSimpleSimView extends FrameView {
    
    static Logger logger = Logger.getLogger(JSimpleSimView.class);
    private static final String HEX = "0123456789ABCDEF";
    @SuppressWarnings("unused")
	private File mainFile;
    private MemHexTableModel memModel;
    private PcHexTableModel pcModel;
    private IrHexTableModel irModel;
    private RegHexTableModel regModel;
    
    // Model for the Stack
    private StackModel stkModel;
    
    private JPanel controlPanel;
    private JPanel memPanel;
    private JPanel PCPanel; 
    private JPanel IRPanel;
    private JPanel CPUButtonPanel;
    private JPanel topCPUPanel;
    private JPanel displayPanel;
    private JPanel registerPanel;
    
    // Stack Panel
    private JPanel stackPanel;
    
    private JPanel buttonPanel;
    private byte[] buffer;
    private File saveFile;
    private boolean isFirstSave;
    private boolean stepClicked;
    public static int READY = 0;
    public static int RUNNING = 1;
    public static int HALTED = 2;
    public static int INVALID_INSTRUCTION = 3;
    private javax.swing.JButton asmButton;
    private javax.swing.JButton breakButton;
    private javax.swing.JButton clearButton;
    private javax.swing.JButton disasmButton;
    @SuppressWarnings("unused")
	private javax.swing.JMenuItem editCopyItem;
    @SuppressWarnings("unused")
	private javax.swing.JMenuItem editCutItem;
    @SuppressWarnings("unused")
	private javax.swing.JMenu editMenu;
    @SuppressWarnings("unused")
	private javax.swing.JMenuItem editPasteItem;
    @SuppressWarnings("unused")
	private javax.swing.JMenuItem editSelectAllItem;
    private javax.swing.JMenuItem fileExitItem;
    private javax.swing.JMenuItem fileSaveAsItem;
    private javax.swing.JMenuItem fileSaveItem;
    private javax.swing.JMenuItem helpMenuHelpItem;
    private javax.swing.JLabel irRegLabel;
    private javax.swing.JTable irTable;
    private javax.swing.JLabel jLabel35;
    private javax.swing.JLabel jLabel36;
    private javax.swing.JLabel stackLabel;
    private javax.swing.JMenuItem jMenuItem7;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JScrollPane jScrollPane6;
    private javax.swing.JScrollPane jScrollPane7;
    
    // Declaring scroll pane for stack
    private javax.swing.JScrollPane stackScrollPane;
    
    @SuppressWarnings("unused")
	private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JTable jTable2;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JList memoryOpCodeList;
    private javax.swing.JTable memoryTable;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JButton openButton;
    private javax.swing.JTextArea outputTextArea;
    private javax.swing.JLabel pcRegLabel;
    private javax.swing.JTable pcTable;
    private javax.swing.JTable registerTable;
    
    // List for the Stack
    private javax.swing.JTable stackTable;
    
    private javax.swing.JButton resetPCButton;
    private javax.swing.JButton runButton;
    private javax.swing.JMenuItem runClearItem;
    private javax.swing.JMenu runRunItem;
    private javax.swing.JMenuItem runStepItem;
    private javax.swing.JButton saveButton;
    private javax.swing.JSlider slider;
    private javax.swing.JButton stepButton;
    private JDialog aboutBox;
    
    /**
     * Default Constructor
     * 
     * @param app
     */
    public JSimpleSimView(SingleFrameApplication app) {
        super(app);

        isFirstSave = true;
        initComponents();
        getFrame().setMinimumSize(new Dimension(800,640));
        getFrame().setPreferredSize(new Dimension(800,640));
    }

    /**
     * Display the About box
     */
    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = JSimpleSimApp.getApplication().getMainFrame();
            aboutBox = new JSimpleSimAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        JSimpleSimApp.getApplication().show(aboutBox);
    }


    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    private void initComponents() {
    	mainPanel = new javax.swing.JPanel();
    	memPanel = new javax.swing.JPanel();
    	controlPanel = new javax.swing.JPanel();
    	PCPanel = new javax.swing.JPanel();
    	IRPanel = new javax.swing.JPanel();
    	CPUButtonPanel = new javax.swing.JPanel();
    	topCPUPanel = new javax.swing.JPanel();
    	displayPanel = new javax.swing.JPanel();
    	registerPanel = new javax.swing.JPanel();
    	
    	// Assignment of the Stack Panel
    	stackPanel = new javax.swing.JPanel();
    	
    	buttonPanel = new javax.swing.JPanel();
        jLabel35 = new javax.swing.JLabel();
        jLabel36 = new javax.swing.JLabel();
        stackLabel = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        memoryTable = new javax.swing.JTable();
        jScrollPane7 = new javax.swing.JScrollPane();
        
        // Assignment of stack scroll pane
        stackScrollPane = new javax.swing.JScrollPane();
        stackScrollPane.setVerifyInputWhenFocusTarget(false);
        stackScrollPane.setRequestFocusEnabled(false);
        stackScrollPane.setFocusTraversalKeysEnabled(false);
        stackScrollPane.setFocusable(false);
        
        jTable2 = new javax.swing.JTable();
        jScrollPane4 = new javax.swing.JScrollPane();
        regModel = new RegHexTableModel(this);
        registerTable = new RegisterTable(this.getRegModel(),this);
        registerTable.setPreferredSize(new Dimension(31, 352));
        
        // stack table
        stkModel = new StackModel(this);
        stackTable = new StackTable(this.getStackModel(),this);
        stackTable.setPreferredSize(new Dimension(0, 0));
        stackTable.setOpaque(false);
        stackTable.setVerifyInputWhenFocusTarget(false);
        stackTable.setSurrendersFocusOnKeystroke(false);
        stackTable.setShowVerticalLines(false);
        stackTable.setShowHorizontalLines(false);
        stackTable.setShowGrid(false);
        stackTable.setRowSelectionAllowed(false);
        stackTable.setRequestFocusEnabled(false);
        stackTable.setIgnoreRepaint(true);
        stackTable.setFocusable(false);
        stackTable.setFocusTraversalKeysEnabled(false);
        stackTable.setFillsViewportHeight(true);
        stackTable.setDragEnabled(false);
        stackTable.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        stackTable.setColumnSelectionAllowed(false);
        stackTable.setCellSelectionEnabled(false);
        stackTable.setAutoCreateRowSorter(true);
        stackTable.setAutoCreateColumnsFromModel(true);
        
        pcRegLabel = new javax.swing.JLabel();
        jScrollPane5 = new javax.swing.JScrollPane();
        pcTable = new javax.swing.JTable();
        irRegLabel = new javax.swing.JLabel();
        jScrollPane6 = new javax.swing.JScrollPane();
        irTable = new javax.swing.JTable();
        resetPCButton = new javax.swing.JButton();
        openButton = new javax.swing.JButton();
        saveButton = new javax.swing.JButton();
        runButton = new javax.swing.JButton();
        stepButton = new javax.swing.JButton();
        breakButton = new javax.swing.JButton();
        clearButton = new javax.swing.JButton();
        slider = new javax.swing.JSlider();
        jScrollPane2 = new javax.swing.JScrollPane();
        memoryOpCodeList = new javax.swing.JList();
        jScrollPane3 = new javax.swing.JScrollPane();
        outputTextArea = new javax.swing.JTextArea();
        asmButton = new javax.swing.JButton();
        disasmButton = new javax.swing.JButton();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem fileOpenItem = new javax.swing.JMenuItem();
        fileSaveItem = new javax.swing.JMenuItem();
        fileSaveAsItem = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JSeparator();
        fileExitItem = new javax.swing.JMenuItem();
        editMenu = new javax.swing.JMenu();
        editCutItem = new javax.swing.JMenuItem();
        editCopyItem = new javax.swing.JMenuItem();
        editPasteItem = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JSeparator();
        editSelectAllItem = new javax.swing.JMenuItem();
        runRunItem = new javax.swing.JMenu();
        runStepItem = new javax.swing.JMenuItem();
        runClearItem = new javax.swing.JMenuItem();
        jMenuItem7 = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        helpMenuHelpItem = new javax.swing.JMenuItem();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();

        mainPanel.setFocusable(false);
        //mainPanel.setMinimumSize(new java.awt.Dimension(800, 600));
        mainPanel.setName("mainPanel"); // NOI18N
        //mainPanel.setPreferredSize(new java.awt.Dimension(800, 600));
	
        // Perseus 2011
        // added floating layout
        mainPanel.setLayout(new BorderLayout());
        memPanel.setLayout(new BorderLayout());
        controlPanel.setLayout(new BorderLayout());
        
        PCPanel.setLayout(new BoxLayout(PCPanel, BoxLayout.X_AXIS));
        IRPanel.setLayout(new BoxLayout(IRPanel, BoxLayout.X_AXIS));
        CPUButtonPanel.setLayout(new BoxLayout(CPUButtonPanel, BoxLayout.Y_AXIS));
        topCPUPanel.setLayout(new BoxLayout(topCPUPanel, BoxLayout.Y_AXIS));
        
        displayPanel.setLayout(new BorderLayout());
        registerPanel.setLayout(new BorderLayout());
        
        // add floating for Stack
        stackPanel.setLayout(new BorderLayout());
        
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));

        mainPanel.add(controlPanel, BorderLayout.LINE_END);
        mainPanel.add(displayPanel, BorderLayout.PAGE_END);

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jsimplesim.JSimpleSimApp.class).getContext().getResourceMap(JSimpleSimView.class);

        // This is the Label "Main Memory"
        jLabel35.setFont(resourceMap.getFont("jLabel35.font")); // NOI18N
        jLabel35.setText(resourceMap.getString("jLabel35.text")); // NOI18N
        jLabel35.setName("jLabel35"); // NOI18N
        memPanel.add(jLabel35, BorderLayout.PAGE_START);

        // This is the label "Registers"
        jLabel36.setFont(resourceMap.getFont("jLabel36.font")); // NOI18N
        jLabel36.setText(resourceMap.getString("jLabel36.text")); // NOI18N
        jLabel36.setName("jLabel36"); // NOI18N
        registerPanel.add(jLabel36, BorderLayout.PAGE_START);


        
        // This is the label "Stack"
        stackLabel.setFont(resourceMap.getFont("stackLabel.font")); // NOI18N
        stackLabel.setText(resourceMap.getString("stackLabel.text")); // NOI18N
        stackLabel.setName("stackLabel"); // NOI18N
        stackPanel.add(stackLabel, BorderLayout.PAGE_START);

        // -------------------------------------------------------------------
        

        
        
        
        jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        jScrollPane1.setName("jScrollPane1"); // NOI18N
        memModel = new jsimplesim.model.MemHexTableModel(this);
        memoryTable = new HexTable(memModel, this);
        // Team Alpha
        // attempt to fix the WARNING: No saved state for jsimplesim.view.components.HexTable[memoryTable,0,0,...
        memoryTable.setName("memoryTable1");
        // end fix
        
        memoryTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
        
        jScrollPane1.setViewportView(memoryTable);
        jScrollPane1.setPreferredSize(new Dimension(640,320));	// Change Dimension 
        
        memPanel.add(jScrollPane1, BorderLayout.CENTER);
        mainPanel.add(memPanel, BorderLayout.CENTER);

        jScrollPane7.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane7.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        jScrollPane7.setName("jScrollPane7"); // NOI18N

        jTable2.setBackground(resourceMap.getColor("jTable2.background")); // NOI18N

    	jTable2.setModel(new javax.swing.table.DefaultTableModel(		// Register label table
            new String [][] {
                {"R0"},
                {"R1"},
                {"R2"},
                {"R3"},
                {"R4"},
                {"R5"},
                {"R6"},
                {"R7"},
                {"R8"},
                {"R9"},
                {"RA"},
                {"RB"},
                {"RC"},
                {"RD"},
                {"RE"},
                {"RF"}
            },
            new String [] {
                ""
            }
	    ) {
            /**
			 * 
			 */
			private static final long serialVersionUID = 1L;
			Class<?>[] types = new Class [] {
                java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false
            };

            @Override
            public Class<?> getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
 
        jTable2.setAutoscrolls(false);
        jTable2.setName("jTable2"); // NOI18N
        jTable2.setRowHeight(22);
        jTable2.setShowHorizontalLines(false);
        jTable2.setShowVerticalLines(false);
        jTable2.getTableHeader().setReorderingAllowed(false);
        jScrollPane7.setPreferredSize(new Dimension(30,320));
        
        jTable2.setTableHeader(null);
        //jTable2.setBorder(BorderFactory.createLineBorder(Color.black));
        jScrollPane7.setViewportView(jTable2);
        
        registerPanel.add(jScrollPane7, BorderLayout.LINE_START);
        
        
        
        // setting up stack scroll pane with the stack table
        stackScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        stackScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        stackScrollPane.setName("stackScrollPane"); 
        
        stackTable.setModel(stkModel);
        stackTable.setFont(new Font("monospaced", Font.PLAIN, 12));
        
        stackTable.setAutoscrolls(true);
        stackTable.setName("stackTable");
        stackTable.setRowHeight(22); 
        stackTable.setTableHeader(null);
        stackTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
        stackTable.setBackground(Color.WHITE);
        stackScrollPane.setViewportView(stackTable);
        
        stackTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        
        stackScrollPane.setPreferredSize(new Dimension(31,320));
        stackPanel.add(stackScrollPane, BorderLayout.CENTER);
        
        
        //This adds the Stack to the View.  Adds the completed stack panel to the control panel
        controlPanel.add(stackPanel, BorderLayout.LINE_START);
        
        //--------------------------------------------------------------------------------
        
        jScrollPane4.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane4.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        jScrollPane4.setName("jScrollPane4"); // NOI18N

        registerTable.setModel(regModel);
        registerTable.setFont(new Font("monospaced", Font.PLAIN, 12));

        registerTable.setAutoscrolls(false);
        registerTable.setName("registerTable"); // NOI18N
        registerTable.setRowHeight(22); 
        registerTable.setTableHeader(null);
        registerTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
        registerTable.setBackground(Color.WHITE);
        jScrollPane4.setViewportView(registerTable);
	
        registerTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
	
        jScrollPane4.setPreferredSize(new Dimension(31,320));
         
        registerPanel.add(jScrollPane4, BorderLayout.CENTER);
        
        //registerPanel.setBorder(BorderFactory.createLineBorder(Color.black));
        
        
        
        controlPanel.add(registerPanel, BorderLayout.CENTER);
	
        topCPUPanel.add(Box.createRigidArea(new Dimension(0,22)));
        
        pcRegLabel.setFont(resourceMap.getFont("pcRegLabel.font")); // NOI18N
        pcRegLabel.setText(resourceMap.getString("pcRegLabel.text")); // NOI18N
        pcRegLabel.setName("pcRegLabel"); // NOI18N
	
        PCPanel.setPreferredSize(new Dimension(50,50));
        //PCPanel.setBorder(BorderFactory.createLineBorder(Color.black));
        
        PCPanel.add(pcRegLabel);
	
        jScrollPane5.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane5.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        jScrollPane5.setName("jScrollPane5"); // NOI18N

        pcTable.setFont(new Font("monospaced", Font.PLAIN, 12));
        pcModel = new PcHexTableModel();
        pcTable.setModel(pcModel);
        
        TableCellRenderer hexCellRenderer = new HexCellRenderer();
        pcTable.setDefaultRenderer(String.class, hexCellRenderer);
        HexCellEditor hce = new HexCellEditor();
        hce.setFont(pcTable.getFont());
        DefaultCellEditor dce = new DefaultCellEditor(hce);
        dce.setClickCountToStart(1);
        pcTable.setDefaultEditor(String.class, dce);
        pcTable.setRowSelectionAllowed(false);
        pcTable.setColumnSelectionAllowed(false);
        pcTable.setAutoscrolls(false);
        pcTable.setName("pcTable"); // NOI18N
        pcTable.setRowHeight(25);
        pcTable.getTableHeader().setReorderingAllowed(false);
        pcTable.setTableHeader(null);
        pcTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
        jScrollPane5.setViewportView(pcTable);
	
        jScrollPane5.setMaximumSize(new Dimension(40,25));
        PCPanel.add(jScrollPane5);
        
		PCPanel.setMaximumSize(new Dimension(100,40));
        PCPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
        topCPUPanel.add(PCPanel);

        irRegLabel.setFont(resourceMap.getFont("irRegLabel.font")); // NOI18N
        irRegLabel.setText(resourceMap.getString("irRegLabel.text")); // NOI18N
        irRegLabel.setName("irRegLabel"); // NOI18N
        
        IRPanel.setPreferredSize(new Dimension(50,23));
        //IRPanel.setBorder(BorderFactory.createLineBorder(Color.black));
        
        IRPanel.add(irRegLabel);
        
        jScrollPane6.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane6.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        jScrollPane6.setName("jScrollPane6"); // NOI18N

        irModel = new IrHexTableModel();
        irTable.setModel(irModel);
        
        irTable.setAutoscrolls(false);
        irTable.setName("irTable"); // NOI18N
        irTable.setRowHeight(19);
        irTable.setRowSelectionAllowed(false);
        irTable.getTableHeader().setReorderingAllowed(false);
        irTable.setShowGrid(false);
        DefaultTableCellRenderer irTableRenderer = new DefaultTableCellRenderer();
        irTableRenderer.setHorizontalAlignment(JLabel.RIGHT);
        irTable.getColumnModel().getColumn(0).setCellRenderer(irTableRenderer);
        irTable.setTableHeader(null);
		jScrollPane6.setViewportView(irTable);
		jScrollPane6.setMaximumSize(new Dimension(50,23));

        IRPanel.add(jScrollPane6);
        IRPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
        
		topCPUPanel.add(IRPanel);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(jsimplesim.JSimpleSimApp.class).getContext().getActionMap(JSimpleSimView.class, this);
        resetPCButton.setAction(actionMap.get("clearPC")); // NOI18N
        resetPCButton.setFont(resourceMap.getFont("resetPCButton.font")); // NOI18N
        resetPCButton.setText(resourceMap.getString("resetPCButton.text")); // NOI18N
        resetPCButton.setMaximumSize(new java.awt.Dimension(50, 23));
        resetPCButton.setMinimumSize(new java.awt.Dimension(50, 23));
        resetPCButton.setName("resetPCButton"); // NOI18N
        resetPCButton.setPreferredSize(new java.awt.Dimension(50, 23));
        PCPanel.add(resetPCButton);        
	
        openButton.setAction(actionMap.get("openItem")); // NOI18N
        openButton.setFont(resourceMap.getFont("clearButton.font")); // NOI18N
        openButton.setText(resourceMap.getString("openButton.text")); // NOI18N
        openButton.setName("openButton"); // NOI18N
        buttonPanel.add(openButton);
        
        saveButton.setAction(actionMap.get("saveItem")); // NOI18N
        saveButton.setFont(resourceMap.getFont("clearButton.font")); // NOI18N
        saveButton.setText(resourceMap.getString("saveButton.text")); // NOI18N
        saveButton.setName("saveButton"); // NOI18N
        buttonPanel.add(saveButton);
	
        slider.setMajorTickSpacing(5);
        slider.setMaximum(10);
        slider.setMinorTickSpacing(1);
        Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
        labelTable.put( new Integer( 0 ), new JLabel("Fast"));
        labelTable.put( new Integer( 10 ), new JLabel("Slow"));
        slider.setLabelTable(labelTable);
        slider.setPaintLabels(true);
        slider.setPaintTicks(true);
        slider.setValue(2);
        slider.setName("slider"); // NOI18N
        slider.setAlignmentX(Component.LEFT_ALIGNMENT);
        slider.setMaximumSize(new Dimension(170,40));        
		CPUButtonPanel.add(slider);

        runButton.setAction(actionMap.get("run")); // NOI18N
        runButton.setFont(resourceMap.getFont("clearButton.font")); // NOI18N
        runButton.setText(resourceMap.getString("runButton.text")); // NOI18N
        runButton.setName("runButton"); // NOI18N
        runButton.setAlignmentX(Component.LEFT_ALIGNMENT);
        CPUButtonPanel.add(runButton);
        
        stepButton.setAction(actionMap.get("step")); // NOI18N
        stepButton.setFont(resourceMap.getFont("clearButton.font")); // NOI18N
        stepButton.setText(resourceMap.getString("stepButton.text")); // NOI18N
        stepButton.setName("stepButton"); // NOI18N
        stepButton.setAlignmentX(Component.LEFT_ALIGNMENT);
        CPUButtonPanel.add(stepButton);
        
        breakButton.setAction(actionMap.get("breakCycle")); // NOI18N
        breakButton.setFont(resourceMap.getFont("clearButton.font")); // NOI18N
        breakButton.setText(resourceMap.getString("breakButton.text")); // NOI18N
        breakButton.setName("breakButton"); // NOI18N
        breakButton.setAlignmentX(Component.LEFT_ALIGNMENT);
        CPUButtonPanel.add(breakButton);
        
        clearButton.setAction(actionMap.get("showClearDialog")); // NOI18N
        clearButton.setFont(resourceMap.getFont("clearButton.font")); // NOI18N
        clearButton.setText(resourceMap.getString("clearButton.text")); // NOI18N
        clearButton.setName("clearButton"); // NOI18N
        clearButton.setAlignmentX(Component.LEFT_ALIGNMENT);
        CPUButtonPanel.add(clearButton);
        
        CPUButtonPanel.add(Box.createVerticalGlue());
        
        //CPUButtonPanel.setBorder(BorderFactory.createLineBorder(Color.black));
        
        topCPUPanel.add(CPUButtonPanel);
	
        controlPanel.add(topCPUPanel, BorderLayout.LINE_END);

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        memoryOpCodeList.setBackground(resourceMap.getColor("memoryOpCodeList.background")); // NOI18N
        memoryOpCodeList.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        memoryOpCodeList.setFont(resourceMap.getFont("memoryOpCodeList.font")); // NOI18N
        
        DefaultListModel dlm = new DefaultListModel();
        int count = 0;
        for (int i = 0; i < 128; i ++) {
            dlm.add(i, this.byteToHex(count) + ":    00,00    invalid");
            count += 2;
        }
        memoryOpCodeList.setModel(dlm);
        memoryOpCodeList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        memoryOpCodeList.setName("memoryOpCodeList"); // NOI18N
        TabListCellRenderer tlRenderer = new TabListCellRenderer();
        memoryOpCodeList.setCellRenderer(tlRenderer);
        jScrollPane2.setViewportView(memoryOpCodeList);

        displayPanel.add(jScrollPane2, BorderLayout.CENTER);
        //jScrollPane2.setBounds(10, 380, 470, 120);

        jScrollPane3.setName("jScrollPane3"); // NOI18N

        outputTextArea.setBackground(resourceMap.getColor("outputTextArea.background")); // NOI18N
        outputTextArea.setColumns(20);
        outputTextArea.setEditable(false);
        outputTextArea.setForeground(resourceMap.getColor("outputTextArea.foreground")); // NOI18N
        outputTextArea.setLineWrap(true);
        outputTextArea.setRows(5);
        outputTextArea.setName("outputTextArea"); // NOI18N
        jScrollPane3.setViewportView(outputTextArea);

        displayPanel.add(jScrollPane3, BorderLayout.LINE_END);
        
        asmButton.setAction(actionMap.get("asmButtonActionPerformed")); // NOI18N
        asmButton.setFont(resourceMap.getFont("asmButton.font")); // NOI18N
        asmButton.setText(resourceMap.getString("asmButton.text")); // NOI18N
        asmButton.setName("asmButton"); // NOI18N
        buttonPanel.add(asmButton);
        
        disasmButton.setAction(actionMap.get("disasmButtonActionPerformed")); // NOI18N
        disasmButton.setFont(resourceMap.getFont("disasmButton.font")); // NOI18N
        disasmButton.setText(resourceMap.getString("disasmButton.text")); // NOI18N
        disasmButton.setName("disasmButton"); // NOI18N
        
        buttonPanel.add(disasmButton);
        
        displayPanel.add(buttonPanel, BorderLayout.PAGE_END);

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        fileOpenItem.setAction(actionMap.get("openItem")); // NOI18N
        fileOpenItem.setName("fileOpenItem"); // NOI18N
        fileMenu.add(fileOpenItem);

        fileSaveItem.setAction(actionMap.get("saveItem")); // NOI18N
        fileSaveItem.setText(resourceMap.getString("fileSaveItem.text")); // NOI18N
        fileSaveItem.setName("fileSaveItem"); // NOI18N
        fileMenu.add(fileSaveItem);

        fileSaveAsItem.setText(resourceMap.getString("fileSaveAsItem.text")); // NOI18N
        fileSaveAsItem.setName("fileSaveAsItem"); // NOI18N
        fileSaveAsItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                fileSaveAsItemActionPerformed(evt);
            }
        });
        fileMenu.add(fileSaveAsItem);

        jSeparator2.setName("jSeparator2"); // NOI18N
        fileMenu.add(jSeparator2);

        fileExitItem.setText(resourceMap.getString("fileExitItem.text")); // NOI18N
        fileExitItem.setName("fileExitItem"); // NOI18N
        fileExitItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                fileExitItemActionPerformed(evt);
            }
        });
        fileMenu.add(fileExitItem);

        menuBar.add(fileMenu);

        runRunItem.setText(resourceMap.getString("runRunItem.text")); // NOI18N
        runRunItem.setName("runRunItem"); // NOI18N

        runStepItem.setAction(actionMap.get("run")); // NOI18N
        runStepItem.setText(resourceMap.getString("runStepItem.text")); // NOI18N
        runStepItem.setName("runStepItem"); // NOI18N
        runRunItem.add(runStepItem);

        runClearItem.setAction(actionMap.get("step")); // NOI18N
        runClearItem.setText(resourceMap.getString("runClearItem.text")); // NOI18N
        runClearItem.setName("runClearItem"); // NOI18N
        runRunItem.add(runClearItem);

        jMenuItem7.setAction(actionMap.get("showClearDialog")); // NOI18N
        jMenuItem7.setName("jMenuItem7"); // NOI18N
        runRunItem.add(jMenuItem7);

        menuBar.add(runRunItem);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        helpMenuHelpItem.setText(resourceMap.getString("helpMenuHelpItem.text")); // NOI18N
        helpMenuHelpItem.setName("helpMenuHelpItem"); // NOI18N
        String helpHS = "helpset.hs";

        HelpSet hs;
        try {
            ClassLoader cl = JSimpleSimView.class.getClassLoader();
            URL hsURL = HelpSet.findHelpSet(cl, helpHS);
            logger.debug("hsURl: " + hsURL.toString() + ", " + hsURL.toExternalForm());
            hs = new HelpSet(null, hsURL);
        } catch (Exception ee) {
            // Say what the exception really is
            System.out.println( "HelpSet " + ee.getMessage());
            System.out.println("HelpSet "+ helpHS +" not found");
            return;
        }
        HelpBroker hb = hs.createHelpBroker();
        helpMenuHelpItem.addActionListener(new CSH.DisplayHelpFromSource(hb));
        helpMenu.add(helpMenuHelpItem);

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        setComponent(mainPanel);
        setMenuBar(menuBar);
       
    }

    private void fileSaveAsItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN
        saveTables();
    }

    private void fileExitItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN
        System.exit(0);
    }

    private void saveTables() {

        JFileChooser fc = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter(
                "BIN Files", "bin");
        fc.setFileFilter(filter);
        fc.addChoosableFileFilter(filter);
        int returnVal = fc.showSaveDialog(this.getFrame());
        this.buffer = getMemModel().getBuffer();
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            this.isFirstSave = false;

            File file = fc.getSelectedFile();
            String fileName = file.getName();
            logger.debug("file name = " + fileName);
            try {
                if (file.exists()) {
                    logger.debug("Writing memoryTable contents to file");
                    store(file);
                    this.saveFile = file;
                } else {
                    logger.debug("Writing memoryTable contents to file");
                    fileName = file.getAbsolutePath();
                    if ((fileName.toLowerCase()).contains(".bin")) {
                        File newFile = new File(fileName);
                        store(newFile);
                        this.saveFile = newFile;
                        logger.debug("Done writing contents to new file");
                    } else {
                        File newFile = new File(fileName + ".bin");
                        store(newFile);
                        this.saveFile = newFile;
                        logger.debug("Done writing contents to new file");
                    }
                }
            } // end try
            catch (Exception e) {
            }
        }

    }

    private void store(File f) throws IOException {
        logger.debug("inside store()");
        if (buffer == null) {
            logger.debug("buffer was null, returning nothing");
            return;
        }
        if (memoryTable.isEditing()) {
            int row = memoryTable.getEditingRow();
            int col = memoryTable.getEditingColumn();
            memoryTable.getCellEditor(row, col).stopCellEditing();
        }

        try {
            logger.debug("file we passed in was " + f.getAbsolutePath());
            FileOutputStream fos = new FileOutputStream(f);
            fos.write(buffer, 0, buffer.length);
            fos.close();
        } catch (Exception e) {
            System.out.println(e);
        }
        logger.debug("done with store...");
    }

    private void openBin(File file) {

        this.mainFile = file;

        if (memoryTable.isEditing()) {
            int row = memoryTable.getEditingRow();
            int col = memoryTable.getEditingColumn();
            memoryTable.getCellEditor(row, col).cancelCellEditing();
        }

        // if (buffer != null)
        // close();

        // Create buffer to hold the entire file

        int fileLength = (int) file.length();
        buffer = new byte[fileLength];

        try {
            FileInputStream fis = new FileInputStream(file);
            fis.read(buffer, 0, buffer.length);
            fis.close();
        } catch (Exception e) {
            System.out.println(e);
        }

        // Create new table data model

        getMemModel().resetBuffer(buffer);
        logger.debug("calling disassembler from openBin()");
        Disassemble.run(getMemModel(), this);
        if (memoryTable.getRowCount() > 0) {
            memoryTable.requestFocus();
            memoryTable.clearSelection();
            memoryTable.setRowSelectionInterval(0, 0);
            memoryTable.setColumnSelectionInterval(1, 1);
            // memoryTable.changeSelection(0, 1, false, false);
            memoryTable.scrollRectToVisible(memoryTable.getCellRect(0, 1, true));
        }

    }

    private void openAsm(File file) {
        try {
            String str = "";
            Scanner sc = new Scanner(file);
            while (sc.hasNextLine()) {
                str += sc.nextLine() + "\n";
            }

            new EditorView(str, this);
        } catch (Exception e) {
        }
    }

    private void open() {

        final JFileChooser fc = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter(
                "ASM and BIN Files", "asm", "bin");
        fc.setFileFilter(filter);
        fc.addChoosableFileFilter(filter);
        // if (evt.getSource() == openButton) {
        int returnVal;
        returnVal = fc.showOpenDialog(this.getFrame());

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            logger.debug("Approve option checked");
            File file = fc.getSelectedFile();
            this.saveFile = file;

            if (file.getName().endsWith("bin")) {
                logger.debug("openBin");
                this.openBin(file);
                this.isFirstSave = false;

            } else {
                logger.debug("openAsm");
                this.openAsm(file);
            }
        // This is where a real application would open the file.
        // log.append("Opening: " + file.getName() + "." + newline);
        } else {
            logger.debug("Open command cancelled by user.");
        }

    }

    /**
     * Resets the memory cells to all zero's. Basically it overwrites the
     * byte array with used in the model.
     */
    public void clearMemoryTable() {

        byte[] clear = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
        };
        getMemModel().resetBuffer(clear);
        logger.debug("calling disassembler from clearMemoryTable()");
        Disassemble.run(this.getMemModel(), this);
    }

    /**
     * The handler for when the  Open button is clicked or when the Open Menu
     * item is clicked.
     */
    @Action
    public void openItem() {
        this.open();
    }

    /**
     * The handler for when the  Save button is clicked or when the Save Menu
     * item is clicked.
     * @throws java.io.IOException
     */
    @Action
    public void saveItem() throws IOException {
        if (this.isFirstSave) {
            this.saveTables();
        } else {
            this.store(this.saveFile);

        }
    }

    /**
     * The handler for when the step button is clicked.
     */
    @Action
    public void step() {
        this.setStepClicked(true);
        Machine.step(getMemModel(), pcModel, irModel, regModel, stkModel, this);
        this.setStepClicked(false);
        //this.highlightList();
        

    }

     public void highlightList() {
        //throw new java.lang.UnsupportedOperationException("Not yet implemented");
         String str = (String) this.pcModel.getValueAt(0, 0);
        logger.debug("PC: " + str);
        int i = Integer.parseInt(str, 16) / 2;
        logger.debug("***After parsing i = " + i);
        this.memoryOpCodeList.ensureIndexIsVisible(i);
        this.memoryOpCodeList.setSelectedIndex(i);
    }


    /**
     * The handler for the button that clears the PC.
     */
    @Action
    public void clearPC() {
        byte[] clear = new byte[]{0};
        this.pcModel.resetBuffer(clear);
        this.highlightList();
    }

    /**
     * This clears out the registers. Resets the byte array in the Register Model.
     */
    public void clearReg() {
    	// Team Alpha edit:
    	// altered the array to ensure both register D (Stack Pointer)
    	// and register E (Base Pointer) now initialize to FF
        byte[] clear = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0};
        this.regModel.resetBuffer(clear);
    }

    /**
     * Stop the execution of the machine.
     */
    @Action
    public void breakCycle() {
        Machine.setSTATE(JSimpleSimView.HALTED);
    }

    /**
     * This is used to output the contents of Register RF to the output area.
     * @param input The string that is sent to the output text area.
     */
    public void output(String input) {
        this.outputTextArea.append(input);
        this.outputTextArea.setCaretPosition(this.outputTextArea.getDocument().getLength());
    }

    /**
     * Takes the dissassembled results in the form of a string and adds it to the
     * dissassembly list.
     * @param input The dissassembly results.
     * @param index The index in the list.
     */
    public void disOut(String input, int index) {
        logger.debug("the input string into disOut = " + input);
        logger.debug("the index into disOut = " + index);
        DefaultListModel dl = (DefaultListModel) this.memoryOpCodeList.getModel();
        logger.debug("got the default list model");
        if (!input.equalsIgnoreCase((String) dl.get(index)) && dl != null) {
            dl.set(index, input);
            if (Machine.getSTATE() != RUNNING && !this.isStepClicked()){
                this.memoryOpCodeList.ensureIndexIsVisible(index);
                this.memoryOpCodeList.setSelectedIndex(index);
            }
        } else {
            if (dl == null) {
                logger.debug("the list model was null..");
            }
        }
    }

    /**
     * The handler for the Run button. Causes an execution thread to run.
     * @return A RunTask
     */
    @Action
    public Task<?, ?> run() {
        return new RunTask(getApplication());
    }

    /**
     * Getter method for the main memory model.
     * @return A MemHexTableModel object.
     */
    public MemHexTableModel getMemModel() {
        return memModel;
    }

    /**
     * Getter method for the register model.
     * @return A RegHexTableModel object
     */
    public RegHexTableModel getRegModel() {
        return regModel;
    }
    
    /**
     * Getter method for the stack model
     * @return A StackModel object
     */
    public StackModel getStackModel(){
    	return stkModel;
    }

    /**
     * Getter method for the dissassembly list model.
     * @return The model assocaited to the Dissassembly List.
     */
    public DefaultListModel getListModel() {
        return (DefaultListModel) this.memoryOpCodeList.getModel();
    }

    /**
     * Setter method for the main memory model.
     * @param memModel The memory model to set.
     */
    public void setMemModel(MemHexTableModel memModel) {
        @SuppressWarnings("unused")
		String index = (String) this.pcModel.getValueAt(0, 0);
    }

    public void trackDisList() {
        //throw new java.lang.UnsupportedOperationException("Not yet implemented");
        String index = (String) this.pcModel.getValueAt(0, 0);
        logger.debug("PC: " + index);
        int i = Integer.parseInt(index, 16);
        logger.debug("index = " + i);
        this.memoryOpCodeList.ensureIndexIsVisible(i);
        this.memoryOpCodeList.setSelectedIndex(i);
    }

    public boolean isStepClicked() {
        return stepClicked;
    }

    public void setStepClicked(boolean stepClicked) {
        this.stepClicked = stepClicked;
    }

    private class RunTask extends org.jdesktop.application.Task<Object, Void> {

        RunTask(org.jdesktop.application.Application app) {
            // Runs on the EDT. Copy GUI state that
            // doInBackground() depends on from parameters
            // to RunTask fields, here.
            super(app);
        }

        @Override
        protected Object doInBackground() {
            // Your Task's code here. This method runs
            // on a background thread, so don't reference
            // the Swing GUI from here.
            try {
                logger.debug("entered doInBackground");
                Machine.run(RUNNING, getMemModel(), pcModel, irModel, regModel,
                        stkModel, JSimpleSimView.this);
            } catch (Exception e) {
            }
            return null;// return your result
        }

        @Override
        protected void succeeded(Object result) {
            // Runs on the EDT. Update the GUI based on
            // the result computed by doInBackground().
        }
    }

    /**
     *
     * @return
     */
    public int getSlider() {
        return slider.getValue();
    }

    /**
     *
     */
    public void clearConsole() {
        this.outputTextArea.setText("");
    }

    /**
     * The handler for the Clear button. Displays a little popup with
     * options to clear out the main memory, registers, output text area, and
     * program counter.
     */
    @Action
    public void showClearDialog() {
        clearView clrView = new clearView(this);
        clrView.setVisible(true);
    }

       
    /**
     * Changes an int into a string.
     * 
     * @param value
     *            The int to convert.
     * @return The string representatin of the int.
     */
    @SuppressWarnings("unused")
	private String intToHex(int value) {
        int hi = (value & 0xFF00) >> 8;
        int lo = (value & 0x00FF);
        return byteToHex(hi) + byteToHex(lo);
    }

    /**
     * Changes a byte into a string.
     * 
     * @param value
     *            The byte to convert.
     * @return The string representation of the byte.
     */
    private String byteToHex(int value) {
        int hi = (value & 0xF0) >> 4;
        int lo = (value & 0x0F);
        return "" + HEX.charAt(hi) + HEX.charAt(lo);
    }

    /**
     *
     * @param row
     * @param col
     */
    public void changeTextColor(int row, int col) {
        // throw new UnsupportedOperationException("Not yet implemented");
        HexCellRenderer hcr = new HexCellRenderer(row, col);
        this.memoryTable.setDefaultRenderer(String.class, hcr);
    }

    /**
     * The handler for the Disasm button. 
     */
    @Action
    public void disasmButtonActionPerformed() {
        String str = Disassemble.createDisassemblyText(this.getListModel());
        new EditorView(str, this);
    }

    @Action
    public void asmButtonActionPerformed() {
        new EditorView("", this);
    }
	
}
